package mrouter

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"gorm.io/gorm"
	"minDeploy.com/common"
	"minDeploy.com/helmv3"
	"minDeploy.com/models"
)

func Result(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		log.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		log.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	var dh models.DeployHistory
	dhs := []models.DeployHistory{}
	models.DB.Find(&dh, "process_id = ?", obj["processId"])
	models.DB.Where("process_id = ?", obj["processId"]).Find(&dhs)
	//models.DB.Find(&dh, "release_name = ? AND release_namespace = ?  AND process_id = ?", obj["name"], obj["namespace"], obj["processId"])
	response, err := json.Marshal(dhs)
	if err != nil {
		panic(err)
	}
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	if dh.Status == "failed" {
		w.WriteHeader(http.StatusBadGateway)
	} else {
		w.WriteHeader(http.StatusOK)
	}
	fmt.Fprintf(w, "%s", response)

}

func List(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		log.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		log.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	nst := obj["namespace"]
	if nst == "" {
		panic("params is wrong")
	}
	namespace, _ := nst.(string)
	helmv3.WG.Add(1)
	helmv3.Limiter <- true
	processId := common.RandomString(25)
	go helmv3.ListRelease(namespace, helmv3.Limiter, helmv3.WG, processId)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"namespace": namespace,
		"processId": processId,
	}
	mstring, _ := json.Marshal(response)
	fmt.Fprintf(w, "%s", mstring)
}

func Get(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		log.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		log.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	nst := obj["namespace"]
	if nst == "" {
		panic("params is wrong")
	}
	nt := obj["name"]
	if nt == "" {
		panic("params is wrong")
	}
	name, _ := nt.(string)
	namespace, _ := nst.(string)
	helmv3.WG.Add(1)
	helmv3.Limiter <- true
	processId := common.RandomString(25)
	go helmv3.GetRelease(name, namespace, helmv3.Limiter, helmv3.WG, processId)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"name":      name,
		"namespace": namespace,
		"processId": processId,
	}
	mstring, _ := json.Marshal(response)
	fmt.Fprintf(w, "%s", mstring)
}
func Install(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		log.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		log.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	log.Println("[ Install Chart with values ] >>>>>>>>>>>>>", obj)
	tmpvalue := obj["name"]
	name, _ := tmpvalue.(string)
	val := helmv3.MakeValues(obj)
	tmpns := obj["namespace"]
	ns, _ := tmpns.(string)
	helmv3.WG.Add(1)
	helmv3.Limiter <- true
	processId := common.RandomString(25)
	go helmv3.InstallChart(name, ns, val, helmv3.Limiter, helmv3.WG, processId)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"name":      name,
		"namespace": ns,
		"processId": processId,
	}
	mstring, _ := json.Marshal(response)
	fmt.Fprintf(w, "%s", mstring)
}
func Uninstall(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		log.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		log.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	//val := makeValues(obj)
	name := obj["name"]
	op, ok := name.(string)
	log.Println(op, ok)
	namespace := obj["namespace"]
	ns, _ := namespace.(string)
	helmv3.WG.Add(1)
	helmv3.Limiter <- true
	processId := common.RandomString(25)
	go helmv3.UninstallChart(op, ns, helmv3.Limiter, helmv3.WG, processId)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"name":      name,
		"namespace": ns,
		"processId": processId,
	}
	mstring, _ := json.Marshal(response)
	fmt.Fprintf(w, "%s", mstring)
}

func Upgrade(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048567))
	if err != nil {
		fmt.Println(err)
		panic("err")
	}
	if err := r.Body.Close(); err != nil {
		fmt.Println(err)
		panic("err")
	}
	obj := make(map[string]interface{})
	err = json.Unmarshal(body, &obj)
	if err != nil {
		log.Println(err)
	}
	log.Println("[ Upgrade Chart with values ] >>>>>>>>>>>>>", obj)
	ns, _ := (obj["namespace"]).(string)
	if ns == "" {
		panic("namespace is required")
	}
	name, _ := (obj["name"]).(string)
	if name == "" {
		panic("name is required")
	}
	//deployment info
	replicas := obj["replicas"]
	image := obj["image"]
	ports := obj["ports"]
	env := obj["env"]
	imagePullPolicy := obj["imagePullPolicy"]
	resources := obj["resources"]
	volumeMounts := obj["volumeMounts"]
	volumes := obj["volumes"]
	dAnnotations := obj["dAnnotations"]
	affinity := obj["affinity"]
	// service info
	servicePorts := obj["servicePorts"]
	serviceType := obj["serviceType"]
	sAnnotations := obj["sAnnotations"]
	startupProbe := obj["startupProbe"]
	livenessProbe := obj["livenessProbe"]
	readinessProbe := obj["readinessProbe"]
	currectValues, err := helmv3.GetValue(name, ns)
	targetDeploy := currectValues["global"].(map[string]interface{})["deployment"].(map[string]interface{})["spec"].(map[string]interface{})
	//deployment update
	if replicas != nil {
		targetDeploy["replicas"] = replicas
	}
	if image != nil {
		targetDeploy["image"] = image
	}
	if ports != nil {
		targetDeploy["ports"] = ports
	}
	if env != nil {
		targetDeploy["env"] = env
	}
	if imagePullPolicy != nil {
		targetDeploy["imagePullPolicy"] = imagePullPolicy
	}
	if resources != nil {
		targetDeploy["resources"] = resources
	}
	if volumeMounts != nil {
		targetDeploy["volumeMounts"] = volumeMounts
	}
	if dAnnotations != nil {
		targetDeploy["dAnnotations"] = dAnnotations
	}
	if affinity != nil {
		targetDeploy["affinity"] = affinity
	}
	if volumes != nil {
		targetDeploy["volumes"] = volumes
	}
	if startupProbe != nil {
		targetDeploy["startupProbe"] = startupProbe
	}
	if livenessProbe != nil {
		targetDeploy["livenessProbe"] = livenessProbe
	}
	if readinessProbe != nil {
		targetDeploy["readinessProbe"] = readinessProbe
	}
	// service update
	targetService := currectValues["global"].(map[string]interface{})["service"].(map[string]interface{})
	if servicePorts != nil {
		targetService["ports"] = servicePorts
	}
	if serviceType != nil {
		targetService["serviceType"] = serviceType
	}
	if sAnnotations != nil {
		targetService["sAnnotations"] = sAnnotations
	}
	helmv3.WG.Add(1)
	helmv3.Limiter <- true
	processId := common.RandomString(25)
	go helmv3.UpgradeChart(name, ns, currectValues, helmv3.Limiter, helmv3.WG, processId)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"name":      name,
		"namespace": ns,
		"processId": processId,
	}
	mstring, _ := json.Marshal(response)
	fmt.Fprintf(w, "%s", mstring)

}

func ResController(db *gorm.DB) {
	for rc := range helmv3.ResChannel {
		log.Println(rc)
		db.Create(rc)
	}
}
